/**
 * Manage photo display
 * @param {EmbeddedView} shell
 * @constructor
 */
function EmbeddedPhotoMediator(shell)
{
	"use strict";

	/** @type {EmbeddedPhotoMediator} */
	var _view = this;
	/** @type {Photo} */
	var _photo = null;
	/** @type {jQuery} */
	var $box = $('#photo');
	/** @type {jQuery} */
	var $oldImg = null;
	/** @type {jQuery} */
	var $newImg = null;

	/**
	 * Update UI to display photo and begin animations
	 * @param {Set} set Set containing current photo
	 * @param {Function} [callback] Method called when photo image has downloaded
	 * @return {EmbeddedView}
	 */
	this.show = function(set, callback)
	{
		_view.stopAnimation();

		/** @type {Photo} */
		var p = set.currentPhoto();
		/** @type {Placement} */
		var panTo = layout(p);

		shell.caption.update(p, set);
		shell.navigation.update(p);

		add(p);

		_view.changed(p, set);

		p.whenReady(function()
		{
			_view.panTo(panTo);
			shell.slideshow.restart();
			if (callback) { callback(); }
		});

		return shell;
	};

	/**
	 * Shadow to implement
	 * @param {Photo} photo
	 * @param {Set} [set]
	 */
	this.changed = function(photo, set) { };

	/**
	 * @return {EmbeddedPhotoMediator}
	 */
	this.stopAnimation = function()
	{
		$box.stop(true);
		return _view;
	};

	/**
	 * Stop animations and hide image
	 * @return {EmbeddedPhotoMediator}
	 */
	this.hide = function()
	{
		$box.stop(true).children('img').fadeOut();
		return _view;
	};

	/**
	 * Pan image container to new position
	 * @param {Placement} placement
	 * @return {EmbeddedPhotoMediator}
	 */
	this.panTo = function(placement)
	{
		if (placement) { $box.animate(placement.clean(), Enum.duration.pan); }
		return _view;
	};

	/**
	 * Add image to display and fade-out old image
	 * @param {Photo} photo
	 */
	function add(photo)
	{
		_photo = photo;

		$oldImg = $newImg;
		$newImg = $(_photo.image);
		$box.append($newImg);
		$newImg.fadeOut(0).fadeIn(Enum.duration.crossfade);

		if ($oldImg)
		{
			$oldImg.fadeOut(Enum.duration.crossfade, function()
			{
				if ($oldImg) { $oldImg.remove(); $oldImg = null; }
			});
		}
	}

	/**
	 * Size photo and display elements for given photo
	 * @param {Photo} photo
	 * @return {Placement} How photo should pan if it exceeds screen size
	 * @see http://api.jquery.com/animate/
	 */
	function layout(photo)
	{
		_photo = photo;

		var maxWidth = window.innerWidth;
		var maxHeight = window.innerHeight;
		var duration = Enum.duration.photoResize;
		/** @type {Placement} */
		var panTo = new Placement();
		/** @type {Placement} */
		var p = new Placement();
		/** @type {Boundary} */
		var boundary = new Boundary();

		_photo.fitToSize(maxWidth, maxHeight);

		p.width = _photo.image.width;
		p.height = _photo.image.height;
		p.top = 0;

		boundary.minLeft = p.left;

		if (p.width > maxWidth)
		{
			p.left = 0;
		}
		else
		{
			boundary.maxLeft = p.left = Math.round((maxWidth - p.width) / 2);
		}

		if (p.height > maxHeight)
		{
			p.top = 0;
			boundary.minTop = panTo.top = maxHeight - p.height;
		}
		boundary.maxTop = p.top;

		// position image box after delay
		$box.animate(p, duration).delay(Enum.duration.photoResize);

		return panTo.clean();
	}
}
